home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / a_utils / perl / msds-prl / bcdsprl4.zoo / popen.c < prev    next >
C/C++ Source or Header  |  1991-12-24  |  4KB  |  205 lines

  1. /* $RCSfile: popen.c,v $$Revision: 4.0.1.1 $$Date: 91/06/07 11:22:52 $
  2.  *
  3.  *    (C) Copyright 1988, 1990 Diomidis Spinellis.
  4.  *
  5.  *    You may distribute under the terms of either the GNU General Public
  6.  *    License or the Artistic License, as specified in the README file.
  7.  *
  8.  * $Log:    popen.c,v $
  9.  * Revision 4.0.1.1  91/06/07  11:22:52  lwall
  10.  * patch4: new copyright notice
  11.  *
  12.  * Revision 4.0  91/03/20  01:34:50  lwall
  13.  * 4.0 baseline.
  14.  *
  15.  * Revision 3.0.1.2  90/08/09  04:04:42  lwall
  16.  * patch19: various MSDOS and OS/2 patches folded in
  17.  *
  18.  * Revision 3.0.1.1  90/03/27  16:11:57  lwall
  19.  * patch16: MSDOS support
  20.  *
  21.  * Revision 1.1  90/03/18  20:32:20  dds
  22.  * Initial revision
  23.  *
  24.  */
  25.  
  26.  
  27. /*
  28.  * Popen and pclose for MS-DOS
  29.  */
  30.  
  31.  
  32. #include <stdlib.h>
  33. #include <stdio.h>
  34. #include <dir.h>
  35. #include <process.h>
  36.  
  37.  
  38. /*
  39.  * Possible actions on an popened file
  40.  */
  41. enum action {
  42.     delete,             /* Used for "r". Delete the tmp file */
  43.     execute                /* Used for "w". Execute the command. */
  44. };
  45.  
  46.  
  47. /*
  48.  * Linked list of things to do at the end of the program execution.
  49.  */
  50. static struct todo {
  51.     FILE *f;            /* File we are working on (to fclose) */
  52.     const char *name;        /* Name of the file (to unlink) */
  53.     const char *command;        /* Command to execute */
  54.     enum action what;        /* What to do (execute or delete) */
  55.     struct todo *next;        /* Next structure */
  56. } *todolist;
  57.  
  58.  
  59.  
  60.  
  61. /* Clean up function */
  62. static int close_pipes(void);
  63.  
  64.  
  65. /*
  66.  * Add a file f running the command command on file name to the list
  67.  * of actions to be done at the end.  The action is specified in what.
  68.  * Return -1 on failure, 0 if ok.
  69.  */
  70. static int
  71. add(FILE *f, const char *command, const char *name, enum action what)
  72. {
  73.     struct todo    *p;
  74.  
  75.  
  76.     if ((p = (struct todo *) malloc(sizeof(struct todo))) == NULL)
  77.         return -1;
  78.     p->f = f;
  79.     p->command = command;
  80.     p->name = name;
  81.     p->what = what;
  82.     p->next = todolist;
  83.     todolist = p;
  84.     return 0;
  85. }
  86.  
  87.  
  88. FILE *
  89. mypopen(const char *command, const char *t)
  90. {
  91.     char buff[128];
  92.     char tpath[64];
  93.     char *name, *tmp_path;
  94.     FILE *f;
  95.     static init = 0;
  96.  
  97.  
  98.     if (!init)
  99.         if (atexit((void (*)())close_pipes) != 0)
  100.             return NULL;
  101.         else
  102.             init++;
  103.  
  104.  
  105.     if ((name = mktemp("PXXXXXX")) == NULL)
  106.         return NULL;
  107.  
  108.     if ((tmp_path = getenv("TMP")) != NULL)
  109.         sprintf(tpath, "%s/%s", tmp_path, name);
  110.     else
  111.         sprintf(tpath, "%s", name);
  112.  
  113.     name = tpath;
  114.  
  115.  
  116.     switch (*t) {
  117.     case 'r':
  118.         sprintf(buff, "%s >%s", command, name);
  119.         if (xsystem(buff) || (f = fopen(name, "r")) == NULL) {
  120.             return NULL;
  121.         }
  122.         if (add(f, command, name, delete)) {
  123.             (void)fclose(f);
  124.             (void)unlink(name);
  125.             return NULL;
  126.         }
  127.         return f;
  128.     case 'w':
  129.         if ((f = fopen(name, "w")) == NULL) {
  130.             return NULL;
  131.         }
  132.         if (add(f, command, name, execute)) {
  133.             (void)fclose(f);
  134.             (void)unlink(name);
  135.             return NULL;
  136.         }
  137.         return f;
  138.     default:
  139.         return NULL;
  140.     }
  141. }
  142.  
  143.  
  144. int
  145. mypclose(FILE *f)
  146. {
  147.     struct todo *p, **prev;
  148.     char buff[256];
  149.     const char *name;
  150.     int status;
  151.  
  152.  
  153.     for (p = todolist, prev = &todolist; p; prev = &(p->next), p = p->next)
  154.         if (p->f == f) {
  155.             *prev = p->next;
  156.             name = p->name;
  157.             switch (p->what) {
  158.             case delete:
  159.                 free(p);
  160.                 if (fclose(f) == EOF) {
  161.                     (void)unlink(name);
  162.                     status = EOF;
  163.                 } else if (unlink(name) < 0)
  164.                     status = EOF;
  165.                 else
  166.                     status = 0;
  167.                 free((void*)name);
  168.                 return status;
  169.             case execute:
  170.                 (void)sprintf(buff, "%s <%s", p->command, p->name);
  171.                 free(p);
  172.                 if (fclose(f) == EOF) {
  173.                     (void)unlink(name);
  174.                     status = EOF;
  175.                 } else if (xsystem(buff)) {
  176.                     (void)unlink(name);
  177.                     status = EOF;
  178.                 } else if (unlink(name) < 0)
  179.                     status = EOF;
  180.                 else
  181.                     status = 0;
  182.                 free((void*)name);
  183.                 return status;
  184.             default:
  185.                 return EOF;
  186.             }
  187.         }
  188.     return EOF;
  189. }
  190.  
  191.  
  192. /*
  193.  * Clean up at the end.  Called by the onexit handler.
  194.  */
  195. static int
  196. close_pipes(void)
  197. {
  198.     struct todo    *p;
  199.  
  200.  
  201.     for (p = todolist; p; p = p->next)
  202.         (void)mypclose(p->f);
  203.     return 0;
  204. }
  205.